package com.framework.config;

import com.framework.enums.PaddleHubModuleEnum;
import com.thread.BaiduOcrThread;
import com.thread.PaddleOcrThread;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Component
public class PaddleHubServerStartConfig implements ApplicationListener<ApplicationStartedEvent> {
    private static final String PADDLE_HUB_PREFIX = "hub serving start --modules ";
    @Resource
    private OcrConfig config;

    @Override
    public void onApplicationEvent(ApplicationStartedEvent applicationStartedEvent) {
        String useOcrType = config.getUseOcrType();
        if (StringUtils.isEmpty(useOcrType)) {
            throw new RuntimeException("-------------------OCR配置错误-------------------");
        }
        if (useOcrType.equals("baiduOcr")) {
            log.info("-------------------使用baiduOcr配置---------------------------------");
            Thread baiduThread = new Thread(new BaiduOcrThread(config));
            baiduThread.start();
            return;
        } else if (useOcrType.equals("paddleOcr")) {
            log.info("-------------------使用paddleOcr配置---------------------------------");
        } else {
            throw new RuntimeException("-------------------OCR配置错误-------------------");
        }

        log.info("-------------------开始启动PaddleHub 服务---------------------------------");
        OcrConfig.PaddleOcr paddleOcr = config.getPaddleOcr();
        String url = paddleOcr.getUrl();
        if (!isIp(url) ) {
            throw new RuntimeException("-------------------IP" + url + "地址配置错误！！！-------------------");
        }
        int port = paddleOcr.getPort();
        if (port == 0) {
            throw new RuntimeException("-------------------端口配置错误-------------------");
        }
        boolean isConnection = isHostConnectable(url, port);
        if (isConnection) {
            throw new RuntimeException("-------------------端口:" + port + "已被使用-------------------");
        }

        StringBuilder paddleHubSuffix = new StringBuilder();
        Map<String, String> moduleMap = paddleOcr.getModuleMap();
        if (moduleMap.size() == 0) {
            throw new RuntimeException("-------------------未配置PaddleHub模块！！！-------------------");
        }
        for (Map.Entry<String, String> module : moduleMap.entrySet()) {
            paddleHubSuffix.append(module.getKey()).append("==").append(module.getValue()).append(" ");
            log.info("模块为：" + PaddleHubModuleEnum.getPaddleHubModuleMap().getOrDefault(module.getKey(), module.getKey()));
        }
        String hubCmd = PADDLE_HUB_PREFIX + paddleHubSuffix;
        Runtime run = Runtime.getRuntime();
        try {
            run.exec(hubCmd);
            String startInfo = "PaddleHub 启动中";
            System.out.print(startInfo);
            long startTime = System.currentTimeMillis();
            while (!isConnection) {
                isConnection = isHostConnectable(url, port);
                Thread.sleep(1000);
                System.out.print(".");
                if ((System.currentTimeMillis() - startTime) / 1000 > 60) {
                    throw new RuntimeException("-------------------PaddleHub 启动超时 请检查配置！！-------------------");
                }

            }
            System.out.println();
            log.info("-------------------PaddleHub 启动成功-------------------");
            log.info("-------------------开始识别！！！！！！-------------------");
            Thread baiduThread = new Thread(new PaddleOcrThread(config));
            baiduThread.start();
        } catch (IOException | InterruptedException e) {
            log.error("PaddleHub 启动失败：" + e.getMessage());
        }

    }

    public static boolean isHostConnectable(String host, int port) {
        Socket socket = new Socket();
        try {
            socket.connect(new InetSocketAddress(host, port));
        } catch (IOException e) {
            return false;
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }
    public static boolean isIp(String ipAddress) {
        String ip = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
        Pattern pattern = Pattern.compile(ip);
        Matcher matcher = pattern.matcher(ipAddress);
        return matcher.matches();
    }
}